define([
  'order!underscore',
  'order!backbone'
], function(_, Backbone){
  var Pagination = function(collection, options){
    var limit = options.limit || 0;
    var offset = options.offset || 0;
    var total = collection.length || 0;
    var addTotal = function() {
      total++;
    };
    
    var removeTotal = function() {
      if(total > 0) {
        total--;
      }
    };

    collection.bind("add", addTotal, this);
    collection.bind("remove", removeTotal, this);
    return _.extend({
      setLimit: function(value) {
        limit = value;
        return this;
      },
      
      getLimit: function() {
        if(limit) {
          return limit;
        } else {
          return 0;
        }
      },
      
      setOffset: function(value, silent) {
        offset = value;
        if(!silent) {
          collection.trigger("pagination:offset", this, offset, options);
        }
        return this;
      },
      
      getOffset: function() {
        return offset;
      },
      
      getTotal: function() {
        return total;
      },

      setTotal: function(value) {
        total = value;
        return this;
      },
      
      nextPage: function() {
        var limit = this.getLimit();
        var max = limit ? Math.ceil(total / limit) : 1,
        currentPage = this.getPage() ;
        if(max >= currentPage+1) {
              this.setPage(currentPage+1);
        }
        return this;
      },
      
      prevPage: function() {
        var limit = this.getLimit();
        var max = limit ? Math.ceil(total / limit) : 1,
        currentPage = this.getPage() ;
        if(currentPage-1 > 0) {
          this.setPage(currentPage-1);
        }
        return this;
      },

      setPage: function(page, silent) {
        var limit = this.getLimit();
        var max = limit ? Math.ceil(total / limit) : 1;
        this.setOffset((page-1)*limit, silent);
/*        if(page <= max) {
        
        } else {
          this.setOffset(0);
        }*/
        return this;
      },
      
      getPage: function() {
        var limit = this.getLimit();
        if(limit) {
          return (offset / limit) + 1;
        }
        return 1;
      },

      models: function() {
        var start = offset,
        end = total,
        limit = this.getLimit();
        if(limit) {
          end = offset+limit;
        }
        if(limit >= collection.models.length) {
          return collection.models;
        } else {
          return collection.models.slice(start, end);
        }
      },
      
      info: function() {
        var MAX_PAGES = 10;
        var limit = this.getLimit(),
        max = limit ? Math.ceil(total / limit) : 1,
        currentPage = this.getPage(),
        prev = 0,
            next = 0,
        pages = [],
        i;

        /**/
        var pageStart = 1;
        if(currentPage - MAX_PAGES/2 < pageStart) {
            pageStart = 1;
        } else {
            pageStart = currentPage - MAX_PAGES / 2;
        }

        var pageEnd = currentPage + MAX_PAGES / 2;
        if(pageEnd > max) {
          pageEnd = max;
        }
        pages.push(pageStart);
        /**/

        if(currentPage+1 <= max) {
          next = currentPage+1;
        }
        if(currentPage-1 > 0) {
          prev = currentPage-1;
        }

        for(i = pageStart+1; i <= pageEnd; i++) {
          pages.push(i);
        }
        
        return {
          total: this.getTotal(),
          page: currentPage,
          prev: prev,
          next: next,
          pages: pages,
          models: this.models()
        };
      }
    }, Backbone.Events);    
  };
  
  var Collection = Backbone.Collection.extend({
    
    initialize: function(models, options) {
      options || (options = {});
      // Pagination
      this.pagination = new Pagination(this, options);
      if(models) {
        this.pagination.setTotal(models.length);
      }
      this.bind("pagination:offset", this.getMore, this);
    },
    
    getMore: function() {
      console.log(this.pagination.info());
      if(this.length <= this.pagination.getTotal() && this.url) {
        this.fetch();
      } else {
        this.trigger("reset");
      }
    },
    
    fetch: function(options) {
      options || (options = {});
      
      var success = options.success;
      options.success = function(collection, resp) {
        if(success) {
          success(model, resp);
        }
        collection.trigger("success_fetch", collection, resp, "This is the success example message!");
      };
      
      var error = options.error;
      options.error = function(collection, resp){
        if(error) {
          error(model, resp);
        }
        collection.trigger("error_fetch", "This is the error example message!", collection, resp);
      };

      var pagination = this.pagination;
      var data = options.data || {};
      data.offset = pagination.getOffset();
      data.limit = pagination.getLimit();
      options.data = data;

      this.trigger("loading");
      return Backbone.Collection.prototype.fetch.call(this, options);
    },

    parse: function(resp) {
      var pagination = this.pagination,
          data = [],
          total = 0;

      // Check if there is a response from the server.
      if(resp) {
        // Check if there is a data object in the response object.
        if(resp.data) {
          data = resp.data;
          total = resp.total;
        } else {
          data = resp;
          total = data.length;
        }
      }
      pagination.setTotal(total);
      return data;
    }
  });
  
  return Collection;
});